#include <base/Server.hpp>
#include <sys/epoll.h>
#include <fcntl.h>

Server::Server(int port) 
    :port_(port), stop_(false), epollfd_(-1), listenfd_(-1)
{ }

Server::~Server() 
{
    
}

bool Server::InitServer()
{
    epollfd_ = epoll_create1(0);
    LogInfo("epollfd_ : %d", epollfd_);
    if (epollfd_ == -1) {
        LogErr("epoll create failed");
        return false;
    }
    listenfd_ = TcpServer::GetInstance(port_)->GetListenSock();
    ev_.data.fd = listenfd_;
    ev_.events = EPOLLIN;
    
    if (epoll_ctl(epollfd_, EPOLL_CTL_ADD, listenfd_, &ev_) == -1) {
        LogErr("epoll_ctl error");
        return false;
    }
    return true;
}

bool Server::Loop()
{
    if (!InitServer()) {
        return false;
    }
    LogInfo("Loop begin..");
    
    while (!stop_ ) {
        int nfds = epoll_wait(epollfd_, events_, MAX_EVENTS, -1);
        if (nfds == -1) {
            LogErr("epoll_wait error");
            if (errno != EINTR) return false;
        }
        LogInfo("epoll_wait return, nfds = %d", nfds);
        for (int i = 0; i < nfds; i++) {
            if (events_[i].data.fd == listenfd_ && (events_[i].events & EPOLLIN)) {
                LogInfo("epoll accept");
                // 从半连接队列中取出到全连接队列
                sockaddr_in endpoint_addr;
                socklen_t endpoint_len = sizeof(endpoint_addr);
                int fd = accept(listenfd_, (struct sockaddr*)&endpoint_addr, (socklen_t *)&endpoint_len);
                if (fd < 0) {
                    LogErr("accept failed");
                    exit(1);
                }
                LogInfo("accept fd:%d", fd);
                // 添加新的fd到epoll的监听队列
                ev_.events = EPOLLIN | EPOLLET | EPOLLRDHUP | EPOLLONESHOT;
                ev_.data.fd = fd;
                if (epoll_ctl(epollfd_, EPOLL_CTL_ADD, fd, &ev_) == -1) {
                    LogErr("add new fd epoll_ctl error");
                    close(fd);
                    return false;
                }
            }  else if (events_[i].events & EPOLLIN) {
                if (events_[i].events & EPOLLRDHUP) { // 对端close fd，这边没处理完业务不close，短连接和长连接场景
                    // if (epoll_ctl(epollfd_, EPOLL_CTL_DEL, events[i].data.fd, nullptr) == -1) {
                    //     LogErr("epoll_ctl EPOLL_CTL_DEL error");
                    // }
                    LogInfo("epoll EPOLLRDHUP fd: %d", events_[i].data.fd);
                    // continue;
                }
                LogInfo("epoll EPOLLIN");
                // 封装任务协议
                LogInfo("epoll_read fd : %d", events_[i].data.fd);
                Task* t = new ReadTask(events_[i].data.fd, epollfd_);
                if (!t -> SetNonBlock()) {
                    LogErr("set fd : %d nonblock failed", t -> GetFd());
                    close(t -> GetFd());
                    continue; // 失败直接跳过这个fd
                }
                // 获取线程池进行处理
                PthreadPool* thread_pool = PthreadPool::GetInstance();
                thread_pool -> PushTask(t);
                LogInfo("push down, i = %d", i);
            } else if (events_[i].events & EPOLLOUT) {
                
            }
        }  
    };
    LogInfo("log thread running");
    return true;
}
